import pandas as pd
import numpy as np
import Core.MongoDB as MongoDB
import datetime
import Core.Gadget as Gadget

#查异动股、指数、期货（最近一个月的涨跌幅超过过去一年日均波动率的2倍标准差）

def StockAbnormalVolatility(database, datetime1, datetime2, instruments):
    dailystd_table = pd.DataFrame()
    monthpct_table = pd.DataFrame()
    for instrument in instruments:
        symbol = instrument['Symbol']
        #print(symbol)
        close_stock = database.find("Quote", symbol + '_Time_86400_Bar', datetime1, datetime2)

        if len(close_stock) == 0:
            continue

        close_info = []
        for bar in close_stock:
            stddatetime = bar['StdDateTime']
            bclose = bar['Values']['BClose']

            close_info.append([stddatetime, bclose])

        close_infotable = pd.DataFrame(close_info, columns=['StdDateTime', 'BClose']).set_index('StdDateTime')
        close_infotable.columns = [symbol]
        # print(len(close_infotable.dropna()))
        if len(close_infotable.dropna()) > 200:
            pct_table = close_infotable.dropna().pct_change()
            std_table = pd.DataFrame((pct_table.dropna().std()))
            std_table.columns = ['daily_std']
            dailystd_table = pd.concat([dailystd_table, std_table], axis=0)
            #print(dailystd_table)
            # close_table = pd.concat([close_table, close_infotable], axis=1)

            month_data = close_infotable.dropna()[-21:]
            month_start = month_data.head(1)
            month_start.index = ['month_pct']
            # print(month_start)
            month_end = month_data.tail(1)
            month_end.index = ['month_pct']
            # print(month_end)
            month_pct = (month_end / month_start - 1).T
            monthpct_table = pd.concat([monthpct_table, month_pct], axis=0)
            #print(monthpct_table)
            info_table = pd.concat([dailystd_table, monthpct_table], axis=1)
    #print(info_table)
    info_table['annualVolatility'] = np.sqrt(245) * info_table['daily_std']
    info_table['monthlyVolatility'] = np.sqrt(20) * info_table['daily_std']
    info_table.to_csv('D:/abnormal_info_stock.csv', encoding = 'GBK')
    abnormal = info_table[abs(info_table['month_pct']) > 2 * np.sqrt(20) * info_table['daily_std']]
    # abnormal.to_csv('D:/abnormal_select.csv', encoding = 'GBK')
    print(abnormal.index.tolist())
    return abnormal.index.tolist()

def IndexAbnormalVolatility(database, datetime1, datetime2, instruments):
    dailystd_table = pd.DataFrame()
    monthpct_table = pd.DataFrame()
    for instrument in instruments:
        symbol = instrument['Symbol']
        #print(symbol)
        close_stock = database.find("Index", symbol + '_Time_86400_Bar', datetime1, datetime2)

        if len(close_stock) == 0:
            continue

        close_info = []
        for bar in close_stock:
            stddatetime = bar['StdDateTime']
            bclose = bar['Close']

            close_info.append([stddatetime, bclose])

        close_infotable = pd.DataFrame(close_info, columns=['StdDateTime', 'Close']).set_index('StdDateTime')
        close_infotable.columns = [symbol]
        # print(len(close_infotable.dropna()))
        if len(close_infotable.dropna()) > 200:
            pct_table = close_infotable.dropna().pct_change()
            std_table = pd.DataFrame((pct_table.dropna().std()))
            std_table.columns = ['daily_std']
            dailystd_table = pd.concat([dailystd_table, std_table], axis=0)
            #print(dailystd_table)
            # close_table = pd.concat([close_table, close_infotable], axis=1)

            month_data = close_infotable.dropna()[-21:]
            month_start = month_data.head(1)
            month_start.index = ['month_pct']
            # print(month_start)
            month_end = month_data.tail(1)
            month_end.index = ['month_pct']
            # print(month_end)
            month_pct = (month_end / month_start - 1).T
            monthpct_table = pd.concat([monthpct_table, month_pct], axis=0)
            #print(monthpct_table)
            info_table = pd.concat([dailystd_table, monthpct_table], axis=1)
    #print(info_table)
    info_table['annualVolatility'] = np.sqrt(245) * info_table['daily_std']
    info_table['monthlyVolatility'] = np.sqrt(20) * info_table['daily_std']
    info_table.to_csv('D:/abnormal_info_index.csv', encoding = 'GBK')
    abnormal = info_table[abs(info_table['month_pct']) > 2 * np.sqrt(20) * info_table['daily_std']]
    # abnormal.to_csv('D:/abnormal_select.csv', encoding = 'GBK')
    print(abnormal.index.tolist())
    return abnormal.index.tolist()
def FutureAbnormalVolatility(database, datetime1, datetime2, instruments):
    abnormal = []
    Information = pd.DataFrame()
    for instrument in instruments:
        if instrument['DateTime2'] > datetime2:
            symbol = instrument['Symbol']
            #print(symbol)
            rawcode = instrument['RawCode']
            exchangecode = instrument['ExchangeCode']
            futureindex = rawcode + '.' + exchangecode
            # print(futureindex)

            data_future = database.find("Future", symbol + '_Time_86400_Bar', datetime1, datetime2)
            data_futureindex = database.find("Future", futureindex + '_Time_86400_Bar', datetime1, datetime2)

            if (len(data_future) == 0) or (len(data_futureindex) == 0):
                continue
            if len(data_futureindex) < 200:
                continue

            close_futureindex = []
            for barr in data_futureindex:
                stddatetime = barr['StdDateTime']
                bclose = barr['Close']
                close_futureindex.append([stddatetime, bclose])
            futureindex_infotable = pd.DataFrame(close_futureindex, columns=['StdDateTime', 'Close']).set_index(
                'StdDateTime')
            futureindex_infotable.columns = [futureindex]
            # print(futureindex_infotable.head())

            pct_futureindex = futureindex_infotable.dropna().pct_change()
            std_futureindex = pd.DataFrame((pct_futureindex.dropna().std()))
            std_futureindex.columns = ['daily_std']
            std_futureindex.index = [symbol]
            # print(std_futureindex)

            close_future = []
            for bar in data_future:
                stddatetime = bar['StdDateTime']
                bclose = bar['Close']
                close_future.append([stddatetime, bclose])
            future_infotable = pd.DataFrame(close_future, columns=['StdDateTime', 'BClose']).set_index('StdDateTime')
            future_infotable.columns = [symbol]
            # print(future_infotable.head())

            month_data = future_infotable.dropna()[-21:]
            month_start = month_data.head(1)
            month_start.index = ['month_pct']
            # print(month_start)
            month_end = month_data.tail(1)
            month_end.index = ['month_pct']
            # print(month_end)
            month_pct = (month_end / month_start - 1).T
            # print(month_pct)

            info_table = pd.concat([std_futureindex, month_pct], axis=1)

            annualVolatility = np.sqrt(245) * info_table.ix[symbol, 'daily_std']
            monthlyVolatility = np.sqrt(20) * info_table.ix[symbol, 'daily_std']
            monthlyPct = info_table.ix[symbol, 'month_pct']

            information = pd.DataFrame(data=[annualVolatility, monthlyVolatility, monthlyPct], columns=[symbol], index=['annualVolatility', 'monthlyVolatility', 'monthlyPct']).T
            Information = pd.concat([Information, information], axis=0)
            #print(Information)
            #print(symbol,"Volatility",annualVolatility, monthlyVolatility ,"Monthly",info_table.ix[symbol, 'month_pct'])

            if abs(info_table.ix[symbol, 'month_pct']) > 2 * monthlyVolatility:
                abnormal.append(symbol)
    Information.to_csv('D:/abnormal_info_future.csv', encoding='GBK')
    print(abnormal)
    return abnormal

#计算
database = MongoDB.MongoDB("10.13.38.5", "27017")
datetime2 = datetime.datetime(2018, 11, 9)
datetime2 = Gadget.ToUTCDateTime(datetime2)
datetime1 = datetime2 - datetime.timedelta(days=366)
datetime1 = Gadget.ToUTCDateTime(datetime1)

stocks = database.find("Instruments", "Stock", datetime1, datetime2)
indexs = database.find("Instruments", "Index")
futures = database.find("Instruments", "Future")
#futureindex = database.find("Instruments", "Future", query={"IsIndex": True})


StockAbnormalVolatility(database, datetime1, datetime2, stocks)
IndexAbnormalVolatility(database, datetime1, datetime2, indexs)
FutureAbnormalVolatility(database, datetime1, datetime2, futures)




